package com.token.aspect;

import com.token.annotation.DecryptField;
import com.token.common.ResultMessage;
import com.token.utils.Base64Util;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.*;


/**
 * 解密切面类
 *
 * @auther: henriy
 * @Date: 2023/12/5
 */
@Slf4j
@Aspect
@Component
public class DecryptAspect {

    @Pointcut("@annotation(com.token.annotation.DecryptMethod)")
    public void pointCut() {
    }

    @Around("pointCut()")
    public Object decryptMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        // 执行原方法并获取返回值
        Object result = joinPoint.proceed();

        // 对带有@DecryptField注解的字段进行解密操作
        if (result != null) {
            if (result instanceof ResultMessage) {
                ResultMessage resultMessage = (ResultMessage) result;
                // 获取实际数据内容
                Object data = resultMessage.getData();
                if (data instanceof Collection<?>) {
                    // 集合
                    data = decryptCollectionFields((Collection<?>) data);
                } else {
                    // 独立对象
                    data = decryptObjectFields(data);
                }

                resultMessage.setData(data);
            }
        }

        return result;
    }

    /**
     * 集合解密方法
     *
     * @param collection
     * @return
     * @throws IllegalAccessException
     */
    private Collection<?> decryptCollectionFields(Collection<?> collection) throws IllegalAccessException {
        for (Object object : collection) {
            decryptObjectFields(object);
        }

        return collection;
    }

    /**
     * 独立对象解密方法
     *
     * @param object
     * @return
     * @throws IllegalAccessException
     */
    private Object decryptObjectFields(Object object) throws IllegalAccessException {
        Field[] fields = object.getClass().getDeclaredFields();

        if (fields.length == 0) {
            throw new IllegalAccessException("字段内容为空");
        }

        for (Field field : fields) {
            // 如果字段带有@DecryptField注解，则对其进行解密操作
            if (field.isAnnotationPresent(DecryptField.class)) {
                field.setAccessible(true);
                Object fieldValue = field.get(object);

                if (fieldValue instanceof String) {
                    String decryptedValue = Base64Util.decryptBase64((String) fieldValue);
                    field.set(object, decryptedValue);
                }
            } else {
                // 如果字段不带有@DecryptField注解，则递归调用decryptObjectFields()方法
                field.setAccessible(true);
                Object fieldValue = field.get(object);

                if (fieldValue != null) {
                    if (fieldValue instanceof Collection<?>) {
                        decryptCollectionFields((Collection<?>) fieldValue);
                    } else if (isCustomObject(fieldValue)) {
                        decryptObjectFields(fieldValue);
                    }
                }
            }
        }

        return object;
    }

    /**
     * 判断一个对象不是八大基本数据类型和String类型
     *
     * @param object
     * @return
     */
    private boolean isCustomObject(Object object) {
        Class<?> objectType = object.getClass();

        // 判断是否为八大基本数据类型
        if (objectType.isPrimitive()) {
            return false;
        }

        return !objectType.equals(String.class);
    }

}
